package com.geek.factory.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.geek.factory.entity.InventoryDistribution;
import com.geek.factory.entity.Material;
import com.geek.factory.entity.Product;
import com.geek.factory.entity.StockCheckDetail;
import com.geek.factory.entity.Shelves;
import com.geek.factory.mapper.StockCheckDetailMapper;
import com.geek.factory.service.IInventoryDistributionService;
import com.geek.factory.service.IMaterialService;
import com.geek.factory.service.IProductService;
import com.geek.factory.service.IStockCheckDetailService;
import com.geek.factory.service.IShelvesService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author author
 * @since 2025-06-29
 */
@Service
@Slf4j
public class StockCheckDetailServiceImpl extends ServiceImpl<StockCheckDetailMapper, StockCheckDetail> implements IStockCheckDetailService {

    @Autowired
    private IInventoryDistributionService inventoryDistributionService;

    @Autowired
    private IProductService productService;

    @Autowired
    private IMaterialService materialService;

    @Autowired
    private IShelvesService shelvesService;

    @Override
    @Transactional(rollbackFor = Exception.class)  // 明确指定回滚异常
    public boolean generateDetailsFromInventory(Integer checkId, Integer warehouseId, String itemType) {
        try {
            log.info("=== 开始从库存分布生成盘点明细 ===");
            log.info("参数: checkId={}, warehouseId={}, itemType={}", checkId, warehouseId, itemType);

            // 查询指定仓库的库存分布
            QueryWrapper<InventoryDistribution> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("warehouse_id", warehouseId);

            // 打印SQL片段，便于调试
            log.info("库存分布查询条件: warehouse_id={}", warehouseId);

            // 根据物品类型过滤
            if ("product".equals(itemType)) {
                queryWrapper.isNotNull("product_id");
                log.info("添加过滤条件: product_id IS NOT NULL");
            } else if ("material".equals(itemType)) {
                queryWrapper.isNotNull("material_id");
                log.info("添加过滤条件: material_id IS NOT NULL");
            } else {
                // 如果未指定类型或指定为"all"，则不添加类型过滤条件，查询所有类型
                log.info("未指定物品类型或指定为all，将查询所有类型的库存");
            }

            // 获取库存分布列表
            List<InventoryDistribution> inventoryList = inventoryDistributionService.list(queryWrapper);

            log.info("查询到库存分布记录数: {}", inventoryList != null ? inventoryList.size() : 0);

            // 打印所有找到的记录，便于调试
            if (inventoryList != null && !inventoryList.isEmpty()) {
                for (InventoryDistribution inv : inventoryList) {
                    log.info("找到库存分布记录: distributionId={}, warehouseId={}, productId={}, materialId={}, quantity={}",
                            inv.getDistributionId(), inv.getWarehouseId(), inv.getProductId(), inv.getMaterialId(), inv.getQuantity());
                }
            }

            if (inventoryList == null || inventoryList.isEmpty()) {
                log.warn("未找到任何符合条件的库存分布记录");
                return false;
            }

            // 先删除已有的明细记录（如果存在）
            QueryWrapper<StockCheckDetail> detailWrapper = new QueryWrapper<>();
            detailWrapper.eq("check_id", checkId);
            if ("product".equals(itemType)) {
                detailWrapper.eq("item_type", "product");
            } else if ("material".equals(itemType)) {
                detailWrapper.eq("item_type", "material");
            }
            long existingCount = this.count(detailWrapper);
            if (existingCount > 0) {
                log.info("删除现有的 {} 条盘点明细记录", existingCount);
                this.remove(detailWrapper);
            }

            List<StockCheckDetail> detailList = new ArrayList<>();

            // 为每个库存分布记录创建盘点明细
            for (InventoryDistribution inventory : inventoryList) {
                StockCheckDetail detail = new StockCheckDetail();
                detail.setCheckId(checkId);

                // 设置产品或原料信息
                if (inventory.getProductId() != null) {
                    // 直接设置产品ID，不查询产品表
                    detail.setProductId(inventory.getProductId());
                    detail.setItemType("product");
                    detail.setUnit("个"); // 设置默认单位

                    log.info("添加产品盘点明细: productId={}, quantity={}",
                            inventory.getProductId(), inventory.getQuantity());
                } else if (inventory.getMaterialId() != null) {
                    // 直接设置原料ID，不查询原料表
                    detail.setMaterialId(inventory.getMaterialId());
                    detail.setItemType("material");
                    detail.setUnit("个"); // 设置默认单位

                    log.info("添加原料盘点明细: materialId={}, quantity={}",
                            inventory.getMaterialId(), inventory.getQuantity());
                } else {
                    // 跳过没有产品或原料ID的记录
                    log.warn("跳过无效库存分布记录: distributionId={}", inventory.getDistributionId());
                    continue;
                }

                // 设置系统库存数量
                detail.setSystemQuantity(inventory.getQuantity());
                // 初始化实际数量为系统数量（待盘点修改）
                detail.setActualQuantity(inventory.getQuantity());
                // 初始差异为0
                detail.setDifference(java.math.BigDecimal.ZERO);

                // 设置货架ID（仓库ID和货柜ID）
                detail.setWarehouseId(inventory.getWarehouseId());
                detail.setShelfId(inventory.getShelfId());
                
                // 获取货架信息并设置位置信息
                if (inventory.getShelfId() != null) {
                    Shelves shelf = shelvesService.getById(inventory.getShelfId());
                    if (shelf != null) {
                        detail.setLocation(shelf.getShelfName());  // 设置货架名称作为位置信息
                    }
                }

                // 设置创建和更新时间
                detail.setCreatedTime(LocalDateTime.now());
                detail.setUpdatedTime(LocalDateTime.now());

                detailList.add(detail);
            }

            log.info("准备保存盘点明细数量: {}", detailList.size());
            if (detailList.isEmpty()) {
                log.warn("没有生成任何盘点明细记录");
                return false;
            }

            // 尝试单条插入，避免批量插入可能的问题
            for (StockCheckDetail detail : detailList) {
                try {
                    boolean success = this.save(detail);
                    log.info("保存单条盘点明细结果: {}, detailId={}", success, detail.getDetailId());
                    if (!success) {
                        log.error("保存单条盘点明细失败: {}", detail);
                    }
                } catch (Exception e) {
                    log.error("保存单条盘点明细异常: {}", detail, e);
                }
            }

            // 验证是否成功保存
            QueryWrapper<StockCheckDetail> checkWrapper = new QueryWrapper<>();
            checkWrapper.eq("check_id", checkId);
            long savedCount = this.count(checkWrapper);
            log.info("验证保存结果: 数据库中的记录数: {}", savedCount);

            return savedCount > 0;

        } catch (Exception e) {
            log.error("生成盘点明细过程中发生异常", e);
            throw e; // 抛出异常，确保事务回滚
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateActualQuantity(Integer detailId, BigDecimal actualQuantity, String updatedBy) {
        try {
            StockCheckDetail detail = this.getById(detailId);
            if (detail == null) {
                log.warn("未找到盘点明细记录: detailId={}", detailId);
                return false;
            }

            detail.setActualQuantity(actualQuantity);
            detail.setDifference(actualQuantity.subtract(detail.getSystemQuantity()));
            detail.setCheckStatus("checked");
            detail.setUpdatedBy(updatedBy);
            detail.setUpdatedTime(LocalDateTime.now());

            boolean success = this.updateById(detail);
            log.info("更新盘点明细实际数量: detailId={}, actualQuantity={}, difference={}, 结果={}",
                    detailId, actualQuantity, detail.getDifference(), success);

            return success;
        } catch (Exception e) {
            log.error("更新盘点明细实际数量时发生异常", e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateLocation(Integer detailId, String location, Integer shelfId, String updatedBy) {
        try {
            StockCheckDetail detail = this.getById(detailId);
            if (detail == null) {
                log.warn("未找到盘点明细记录: detailId={}", detailId);
                return false;
            }

            detail.setLocation(location);
            detail.setShelfId(shelfId);
            detail.setUpdatedBy(updatedBy);
            detail.setUpdatedTime(LocalDateTime.now());

            boolean success = this.updateById(detail);
            log.info("更新盘点明细位置信息: detailId={}, location={}, shelfId={}, 结果={}",
                    detailId, location, shelfId, success);

            return success;
        } catch (Exception e) {
            log.error("更新盘点明细位置信息时发生异常", e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCheckStatus(Integer detailId, String checkStatus, String updatedBy) {
        try {
            StockCheckDetail detail = this.getById(detailId);
            if (detail == null) {
                log.warn("未找到盘点明细记录: detailId={}", detailId);
                return false;
            }

            detail.setCheckStatus(checkStatus);
            detail.setUpdatedBy(updatedBy);
            detail.setUpdatedTime(LocalDateTime.now());

            boolean success = this.updateById(detail);
            log.info("更新盘点明细状态: detailId={}, checkStatus={}, 结果={}",
                    detailId, checkStatus, success);

            return success;
        } catch (Exception e) {
            log.error("更新盘点明细状态时发生异常", e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateCheckStatus(List<Integer> detailIds, String checkStatus, String updatedBy) {
        try {
            if (detailIds == null || detailIds.isEmpty()) {
                log.warn("批量更新状态的明细ID列表为空");
                return false;
            }

            List<StockCheckDetail> details = this.listByIds(detailIds);
            if (details.isEmpty()) {
                log.warn("未找到需要更新状态的盘点明细记录");
                return false;
            }

            LocalDateTime now = LocalDateTime.now();
            for (StockCheckDetail detail : details) {
                detail.setCheckStatus(checkStatus);
                detail.setUpdatedBy(updatedBy);
                detail.setUpdatedTime(now);
            }

            boolean success = this.updateBatchById(details);
            log.info("批量更新盘点明细状态: detailIds={}, checkStatus={}, 结果={}",
                    detailIds, checkStatus, success);

            return success;
        } catch (Exception e) {
            log.error("批量更新盘点明细状态时发生异常", e);
            throw e;
        }
    }

    @Override
    public List<StockCheckDetail> getDifferenceDetails(Integer checkId) {
        try {
            QueryWrapper<StockCheckDetail> wrapper = new QueryWrapper<>();
            wrapper.eq("check_id", checkId)
                    .ne("difference", 0)
                    .orderByDesc("abs(difference)");

            List<StockCheckDetail> details = this.list(wrapper);
            log.info("查询差异明细: checkId={}, 找到{}条记录", checkId, details.size());

            return details;
        } catch (Exception e) {
            log.error("查询差异明细时发生异常", e);
            throw e;
        }
    }

    @Override
    public Map<String, Object> getDetailStats(Integer checkId) {
        try {
            Map<String, Object> stats = new HashMap<>();
            
            QueryWrapper<StockCheckDetail> wrapper = new QueryWrapper<>();
            wrapper.eq("check_id", checkId);

            // 总记录数
            long total = this.count(wrapper);
            stats.put("total", total);

            // 已盘点数量
            wrapper.clear();
            wrapper.eq("check_id", checkId)
                    .eq("check_status", "checked");
            long checked = this.count(wrapper);
            stats.put("checked", checked);

            // 差异数量
            wrapper.clear();
            wrapper.eq("check_id", checkId)
                    .ne("difference", 0);
            long differences = this.count(wrapper);
            stats.put("differences", differences);

            log.info("获取盘点明细统计: checkId={}, total={}, checked={}, differences={}",
                    checkId, total, checked, differences);

            return stats;
        } catch (Exception e) {
            log.error("获取盘点明细统计时发生异常", e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateDetails(List<StockCheckDetail> details, String updatedBy) {
        try {
            if (details == null || details.isEmpty()) {
                log.warn("批量更新的明细列表为空");
                return false;
            }

            LocalDateTime now = LocalDateTime.now();
            for (StockCheckDetail detail : details) {
                detail.setUpdatedBy(updatedBy);
                detail.setUpdatedTime(now);
            }

            boolean success = this.updateBatchById(details);
            log.info("批量更新盘点明细: 更新{}条记录, 结果={}", details.size(), success);

            return success;
        } catch (Exception e) {
            log.error("批量更新盘点明细时发生异常", e);
            throw e;
        }
    }
}